package com.ice.work.moment.crawler.processor;

import cn.hutool.core.util.ReflectUtil;
import cn.hutool.core.util.StrUtil;
import com.honeybee.cloud.framework.common.enums.DataStatusEnum;
import com.honeybee.cloud.framework.common.idwork.IdWorker;
import com.ice.work.moment.crawler.service.ICommentService;
import com.ice.work.moment.crawler.service.IShareService;
import com.ice.work.moment.facade.crawler.analytical.CommentAnalyticalObject;
import com.ice.work.moment.facade.crawler.dto.ShareDTO;
import com.ice.work.moment.facade.crawler.enums.CommentEnum;
import com.ice.work.moment.facade.crawler.mapper.AnalyticalObjectConvertMapper;
import com.ice.work.moment.facade.crawler.model.Comment;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.CollectionUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
import us.codecraft.webmagic.Page;
import us.codecraft.webmagic.processor.PageProcessor;
import us.codecraft.webmagic.selector.Html;
import us.codecraft.webmagic.selector.Selectable;

import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @Description 股票评论
 * @Author DELL
 * @Create 2019-04-29
 * @Since 1.0.0
 */
@Slf4j
@Component
@SuppressWarnings("all")
public class CommentProcessor extends BaseProcessor implements PageProcessor {

    @Autowired
    private IdWorker idWorker;
    @Autowired
    private IShareService shareService;
    @Autowired
    private ICommentService commentService;

    @Override
    public void process(Page page) {
        try {
            Html html = page.getHtml();
            log.info("股票评论原文:{}", html.get());
            List<Selectable> trSelectableList = html.xpath("//*[@id='content']/table[2]/tbody/tr").nodes();
            if (CollectionUtils.isEmpty(trSelectableList) || CollectionUtils.size(trSelectableList) == 1) {
                log.info("无法获得股票评论原文");
                return;
            }
            int i = 1;
            do {

                Selectable trSelectable = trSelectableList.get(i);
                log.info("爬取股票评论内容:{}", trSelectable.get());
                CommentAnalyticalObject commentAnalyticalObject = new CommentAnalyticalObject();
                commentAnalyticalObject = getValues(commentAnalyticalObject, trSelectable);
                i++;
                log.info("股票评论内容处理结果:{}", commentAnalyticalObject);
                if (Objects.isNull(commentAnalyticalObject)) {
                    log.error("无法获得股票评论解析数据");
                    continue;
                }
                ShareDTO shareDTO = shareService.findByShareCode(commentAnalyticalObject.getShareCode());
                if (Objects.isNull(shareDTO)) {
                    log.error("无法获取到股票代码:{}", commentAnalyticalObject.getShareCode());
                    continue;
                }
                Comment comment = AnalyticalObjectConvertMapper.INSTANCE.toModel(commentAnalyticalObject);
                comment.setId(idWorker.nextId());
                comment.setDataStatus(DataStatusEnum.VALID.key);
                comment.setCreateAt(new Date());
                comment.setShareId(shareDTO.getId());
                commentService.saveOrUpdate(comment);
            } while (i < trSelectableList.size());

        } catch (Exception e) {
            log.error("爬取股票评论异常", e);
        }

    }


    /**
     * 获取列值
     *
     * @param trSelectable
     * @return
     */
    private CommentAnalyticalObject getValues(CommentAnalyticalObject obj, Selectable trSelectable) {
        Class clazz = obj.getClass();
        Field[] fields = ReflectUtil.getFields(clazz);
        Method[] methods = ReflectUtil.getMethods(clazz);
        Map<String, Field> fieldMap = Arrays.stream(fields).collect(Collectors.toMap(Field::getName, a -> a, (k1, k2) -> k1));
        Map<String, Method> methodMap = Arrays.stream(methods).collect(Collectors.toMap(Method::getName, a -> a, (k1, k2) -> k1));
        List<Selectable> tdSelectableList = trSelectable.xpath("//td").nodes();
        for (int j = 0; j < tdSelectableList.size(); j++) {
            try {
                Selectable tdSelectable = tdSelectableList.get(j);
                String code = CommentEnum.getCodeByKey(j);
                if (Objects.isNull(code)) {
                    continue;
                }
                Field field = fieldMap.get(code);
                if (Objects.isNull(field)) {
                    continue;
                }
                Method method = methodMap.get(StrUtil.genSetter(field.getName()));
                if (Objects.isNull(method)) {
                    continue;
                }

                //获取内容
                String value = null;
                List<Selectable> nobrSelectableList = tdSelectable.xpath("//nobr").nodes();
                if (CollectionUtils.isNotEmpty(nobrSelectableList)) {
                    value = tdSelectable.xpath("//nobr/text()").get();
                }
                if (StringUtils.isEmpty(value)) {
                    List<Selectable> aSelectableList = tdSelectable.xpath("//a").nodes();
                    if (CollectionUtils.isNotEmpty(aSelectableList)) {
                        value = tdSelectable.xpath("//a/text()").get();
                    }
                }
                if (StringUtils.isEmpty(value)) {
                    value = trSelectable.xpath("//td[" + (j + 1) + "]/text()").get();
                }

                method.invoke(obj, StrUtil.trim(value));
                continue;
            } catch (Exception e) {
                log.error("爬取A股列表内容处理异常", e);
            }
        }
        return obj;
    }
}
